export function generateSudoku() {
    const grid = Array.from({ length: 9 }, () => Array(9).fill(0));

    function isValid(grid, row, col, num) {
        for (let x = 0; x < 9; x++) {
            if (grid[row][x] === num || grid[x][col] === num || grid[3 * Math.floor(row / 3) + Math.floor(x / 3)][3 * Math.floor(col / 3) + (x % 3)] === num) {
                return false;
            }
        }
        return true;
    }

    function solve(grid) {
        const empty = findEmpty(grid);
        if (!empty) return true;

        const { row, col } = empty;

        // 生成一个随机数列表，并打乱顺序
        const numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9].sort(() => 0.5 - Math.random());

        for (let num of numbers) {
            if (isValid(grid, row, col, num)) {
                grid[row][col] = num;
                if (solve(grid)) return true;
                grid[row][col] = 0; // 回溯
            }
        }
        return false; // 触发回溯
    }

    function findEmpty(grid) {
        for (let row = 0; row < 9; row++) {
            for (let col = 0; col < 9; col++) {
                if (grid[row][col] === 0) {
                    return { row, col };
                }
            }
        }
        return null;
    }

    if (solve(grid)) {
        return grid;
    } else {
        return null; // 如果无法生成有效的数独，则返回null
    }
}

export function clearRandomPositions(grid, num) {
    // 获取所有可能的索引位置
    const positions = [];
    for (let i = 0; i < grid.length; i++) {
        for (let j = 0; j < grid[i].length; j++) {
            positions.push({row: i, col:j});
        }
    }

    // 随机选取10个不重复的索引位置
    const randomPositions = [];
    while (randomPositions.length < num) {
        const randomIndex = Math.floor(Math.random() * positions.length);
        const {row, col} = positions.splice(randomIndex, 1)[0];
        randomPositions.push({row, col});
    }

    // 将选取的位置的值设置为0
    randomPositions.forEach(({row, col}) => {
        grid[row][col] = 0;
    });

    return randomPositions;
}


export function isSudokuValid(grid) {
    // 首先检查数独网格中是否有空值或0
    for (let row of grid) {
        for (let num of row) {
            if (num === 0) {
                return false; // 发现空值，验证不通过
            }
        }
    }
    for (let i = 0; i < 9; i++) {
        // 检查行和列
        if (!isRowAndColValid(grid, i, i)) {
            return false;
        }
        // 检查3x3宫格
        if (!isBoxValid(grid, i - i % 3, i - i % 3)) {
            return false;
        }
    }
    return true;
}

function isRowAndColValid(grid, row, col) {
    const rowSet = new Set();
    const colSet = new Set();
    for (let i = 0; i < 9; i++) {
        // 检查行
        if (grid[row][i] !== 0 && !rowSet.has(grid[row][i])) {
            rowSet.add(grid[row][i]);
        } else if (grid[row][i] !== 0) {
            // 发现重复数字
            return false;
        }
        // 检查列
        if (grid[i][col] !== 0 && !colSet.has(grid[i][col])) {
            colSet.add(grid[i][col]);
        } else if (grid[i][col] !== 0) {
            // 发现重复数字
            return false;
        }
    }
    return true;
}

function isBoxValid(grid, startRow, startCol) {
    const boxSet = new Set();
    for (let row = 0; row < 3; row++) {
        for (let col = 0; col < 3; col++) {
            const num = grid[startRow + row][startCol + col];
            if (num !== 0 && !boxSet.has(num)) {
                boxSet.add(num);
            } else if (num !== 0) {
                // 发现重复数字
                return false;
            }
        }
    }
    return true;
}

export function getPositionsOfNum(ary, row, col, num) {
    if (!num) {
        return []
    }
    const positions = [];


    // 检查行
    for (let i = 0; i < 9; i++) {
        if (ary[row][i] === num && i !== col) {
            positions.push({ row: row, col: i, type: "row" });
        }
    }

    // 检查列
    for (let i = 0; i < 9; i++) {
        if (ary[i][col] === num && i !== row) {
            positions.push({ row: i, col: col, type: "col" });
        }
    }

    // 检查 9 宫格
    const startRow = Math.floor(row / 3) * 3;
    const startCol = Math.floor(col / 3) * 3;

    for (let r = startRow; r < startRow + 3; r++) {
        for (let c = startCol; c < startCol + 3; c++) {
            if (ary[r][c] === num && (r !== row || c !== col)) {
                positions.push({ row: r, col: c, type: "box" });
            }
        }
    }

    return positions;
}

export function getGroupNumber(row, col) {
    return Math.floor(row / 3) * 3 + Math.floor(col / 3) + 1;
}